Skip to main content
Version: 1.0.0

Creating range plot

What is a range plot?

Range plots show exactly two dots on a line and connect them. These are great if you want to draw attention to the distance between the values more than to the values themselves. For example a comparison between the minimum and maximum temperature over 10 years can be visualized better with a range plot.

Using the share operator

Share operator creates a new composed variable instance from multiple variables. This is required when we need to map multiple fields in a single axis. For example, we want to show minimum temperature and maximum temperature on y-axis, then we have to create a shared field.

Pass fields to plot in the share operator and attach the result in rows/columns of the chart:

const { muze } = viz;
const { share } = muze.Operators;

const sharedField = share("maxTemp", "minTemp");

muze.canvas().rows([sharedField]).columns(["date"]).mount("#chart");

Example

Muze's box plot sample uses a shared field in rows.

const { muze } = viz;

const data = [
  {
    Maker: "BMW",
    min: 3000,
    q1: 4000,
    median: 4800,
    q3: 5200,
    max: 5800,
  },
  {
    Maker: "Chevrolet",
    min: 2800,
    q1: 3500,
    median: 4200,
    q3: 4700,
    max: 5200,
  },
  {
    Maker: "Dodge",
    min: 3100,
    q1: 3900,
    median: 5000,
    q3: 5500,
    max: 6000,
  },
  {
    Maker: "Ford",
    min: 2700,
    q1: 3400,
    median: 3900,
    q3: 4400,
    max: 5000,
  },
  {
    Maker: "Peugeot",
    min: 2500,
    q1: 3000,
    median: 3100,
    q3: 3400,
    max: 3700,
  },
  {
    Maker: "Volvo",
    min: 2900,
    q1: 3300,
    median: 3600,
    q3: 4000,
    max: 4400,
  },
  {
    Maker: "Toyota",
    min: 2600,
    q1: 3700,
    median: 4500,
    q3: 4900,
    max: 5300,
  },
  {
    Maker: "Honda",
    min: 2400,
    q1: 3200,
    median: 4000,
    q3: 4300,
    max: 4700,
  },
  {
    Maker: "Nissan",
    min: 2500,
    q1: 3000,
    median: 3800,
    q3: 4200,
    max: 4600,
  },
  {
    Maker: "Mercedes-Benz",
    min: 3400,
    q1: 4500,
    median: 5200,
    q3: 5700,
    max: 6100,
  },
  {
    Maker: "Audi",
    min: 2900,
    q1: 3600,
    median: 4100,
    q3: 4600,
    max: 5100,
  },
];

const schema = [
  {
    name: "Maker",
    type: "dimension",
  },
  {
    name: "min",
    type: "measure",
  },
  {
    name: "q1",
    type: "measure",
  },
  {
    name: "median",
    type: "measure",
  },
  {
    name: "q3",
    type: "measure",
  },
  {
    name: "max",
    type: "measure",
  },
];

let dm = new DataModel(await DataModel.loadData(data, schema));

muze
  .canvas()
  .rows([muze.Operators.share("min", "max", "q1", "median", "q3")])
  .columns(["Maker"])
  .layers([
    {
      mark: "bar",
      encoding: {
        y: "q3",
        y0: "median",
        color: "Maker",
      },
    },
    {
      mark: "bar",
      encoding: {
        y: "median",
        y0: "q1",
        color: "Maker",
      },
    },
    {
      mark: "tick",
      encoding: {
        y: "q1",
        y0: "min",
        color: {
          value: () => "black",
        },
      },
    },
    {
      mark: "tick",
      encoding: {
        y: "median",
        color: {
          value: () => "#fff",
        },
      },
    },
    {
      mark: "tick",
      encoding: {
        y: "max",
        y0: "q3",
        color: {
          value: () => "black",
        },
      },
    },
  ])
  .config({
    axes: {
      y: {
        name: "Horsepower Distribution",
      },
    },
  })
  .title("Box Plot", { position: "top", align: "center" })
  .data(dm)
  .width(800)
  .height(800)
  .mount("#chart");

Using encoding channels to define a range plot

Each layer has an encoding object configuration which accepts x0, x, y0, y and color parameters.

To create a vertical range plot, map fields to y0 and y. To create a horizontal range plot, map fields to x0 and x. Optionally, also pass a function in color.value to color the layer plots.

Example

const { muze, getDataFromSearchQuery } = viz;

const data = getDataFromSearchQuery();

let dm = new DataModel(data);
const share = muze.Operators.share;

// Min value of weight for a group
dm = dm.calculateVariable(
  {
    name: "Min Weight",
    type: "measure",
    defAggFn: "min",
  },
  ["Weight_in_lbs"],
  (val) => val,
);

// Max value of weight for a group
dm = dm.calculateVariable(
  {
    name: "Max Weight",
    type: "measure",
    defAggFn: "max",
  },
  ["Weight_in_lbs"],
  (val) => val,
);

muze
  .canvas()
  .rows([share("Max Weight", "Min Weight")])
  .columns(["Year"])
  .layers([
    {
      mark: "tick",
      encoding: {
        y: "Max Weight",
        y0: "Min Weight",
        size: {
          value: () => 0.001,
        },
      },
      interpolate: "catmullRom",
    },
  ])
  .config({
    axes: {
      y: {
        name: "Weight",
      },
    },
  })
  .data(dm)
  .width(700)
  .height(700)
  .mount("#chart");